"""
文件名称: performance_calculations.py
功能: 计算系统性能指标的函数文件（如碳效、碳排放量、数据量等）
作者: 喻越
创建日期: 2025-01-15
"""
import numpy as np
from ..parameter.constant import const


def rate_sum_calculation(x_bs_ue, h_bs_ue, l_bs_ue, rb_req):
    '''
    计算各用户速率与总速率
    :param x_bs_ue: 连接矩阵
    :param h_bs_ue: 信道矩阵
    :param l_bs_ue: 距离矩阵
    :param rb_req: 需求资源块矩阵
    :return: 各用户在当前连接下的速率与总速率
    '''
    ue_num = x_bs_ue.shape[0]
    bs_num = x_bs_ue.shape[1]
    # 计算用户总速率
    one = np.ones(shape=[ue_num, bs_num])

    RB_W = np.tile(const.RB_W, (ue_num, 1))
    # 用户速率矩阵 shape=[ue_num, bs_num]
    r_ue_temp = RB_W * (x_bs_ue * rb_req) * np.log2(
        one + (const.RB_PR * rb_req * h_bs_ue) / (np.power(l_bs_ue, const.ALPHA) * const.NOISE))
    # 用户速率矩阵 shape=[ue_num, 1] 升维后转置
    r_ue = np.transpose(np.expand_dims(np.sum(r_ue_temp, axis=1), 0))
    rb_req_access = np.transpose(np.expand_dims(np.sum(x_bs_ue * rb_req, axis=1), 0))  # 用户在当前接入下所需的资源块
    # 用户服务质量满足情况 考虑用户未接入的情况
    ue_status = np.sum(x_bs_ue, 1)[:, None]
    delta_connected = (np.sum(ue_status)) / ue_num

    return r_ue, ue_status, delta_connected


# 计算R:所有用户的总速率
def compute_R(res_x_bs_ue, h_bs_ue, l_bs_ue, rb_req):
    """
    计算R:所有用户的总速率
    :param res_x_bs_ue:
    :param h_bs_ue:
    :param l_bs_ue:
    :param rb_req:
    :return: 所有用户的总速率
    """
    r_ue, _, _ = rate_sum_calculation(res_x_bs_ue, h_bs_ue, l_bs_ue, rb_req)
    return np.sum(r_ue)


# 计算B:1h所有用户的数据量 R*3600
def compute_B(res_x_bs_ue, h_bs_ue, l_bs_ue, rb_req):
    """
    计算B:1h所有用户的数据量 R*3600
    :param res_x_bs_ue:
    :param h_bs_ue:
    :param l_bs_ue:
    :param rb_req:
    :return: 1h所有用户的数据量 R*3600
    """
    R = compute_R(res_x_bs_ue, h_bs_ue, l_bs_ue, rb_req)
    B = R * 3600
    return B


def bs_energy_consumption_calculation(bs_status, x_bs_ue, rb_req):
    '''
    依据休眠情况和连接情况，计算基站能耗
    :param bs_status: 基站休眠状态
    :param x_bs_ue: 连接状态
    :param rb_req: 资源块需求
    :return: 基站能耗，基站已用资源块
    '''
    bs_num = x_bs_ue.shape[1]  # 求取基站数
    # 当前接入下各基站使用的资源块 shape=[1,bs_num]
    bs_rb_access = np.sum((x_bs_ue * rb_req), 0) * bs_status
    p_static = np.zeros(shape=[1, bs_num])  # 基站静态功率
    for i in range(bs_num):
        if i == 0:
            p_static[0][i] = const.P_STATIC_SLEEP_MACRO if bs_status[0][i] == 0 else const.P_STATIC_WORK_MACRO
        else:
            p_static[0][i] = const.P_STATIC_SLEEP_MICRO if bs_status[0][i] == 0 else const.P_STATIC_WORK_MICRO

    p_bs = const.RB_PR * bs_rb_access / const.ETA + p_static  # 包括休眠基站 shape=[1,bs_num]

    return p_bs, bs_rb_access


# 计算碳排放量
def compute_E(res_x_bs_ue, p_pv, bs_status, rb_req):
    """
    :param res_x_bs_ue:
    :param p_pv:
    :param bs_status:
    :param rb_req:
    :return: 总的碳排放量，消纳光伏数据，市电
    """
    zero_bs = np.zeros_like(p_pv)
    p_available = p_pv
    p_bs, _ = bs_energy_consumption_calculation(bs_status, res_x_bs_ue, rb_req)  # shape=[1,bs_num]
    return const.ETA_GRID * np.sum(np.maximum(p_bs - p_available, zero_bs)) + const.ETA_PV * np.sum(
        np.minimum(p_bs, p_available))


def compute_E_vector(res_x_bs_ue, p_pv, bs_status, rb_req):
    zero_bs = np.zeros_like(p_pv)
    p_available = p_pv
    p_bs, _ = bs_energy_consumption_calculation(bs_status, res_x_bs_ue, rb_req)  # shape=[1,bs_num]
    return const.ETA_GRID * np.maximum(p_bs - p_available, zero_bs) + const.ETA_PV * np.minimum(p_bs, p_available)


def compute_comsume_pv_city_e(res_x_bs_ue, p_pv, bs_status, rb_req):
    """
    计算得到消耗的光伏consume_pv以及市电city_e
    :return:
    """
    zero_bs = np.zeros_like(p_pv)
    p_available = p_pv
    p_bs, _ = bs_energy_consumption_calculation(bs_status, res_x_bs_ue, rb_req)  # shape=[1,bs_num]
    return np.sum(np.minimum(p_bs, p_available)), np.sum(np.maximum(p_bs - p_available, zero_bs))


# 计算能耗P_bs
def compute_P(bs_status, res_x_bs_ue, rb_req):
    p_bs, _ = bs_energy_consumption_calculation(bs_status, res_x_bs_ue, rb_req)
    return np.sum(p_bs)


def compute_delta_pv(res_t_bs_bs, res_C, res_D, p_pv, p_escape):
    p_available = compute_p_available(res_t_bs_bs, res_C, res_D, p_pv)
    delta_pv = (np.sum(p_available) - np.sum(p_escape)) / np.sum(p_available)  # nan=0/0
    if np.isnan(delta_pv): delta_pv = 1.0
    return delta_pv


# 计算能效 EE
def compute_EE(res_x_bs_ue, bs_status, h_bs_ue, l_bs_ue, rb_req):
    B = compute_B(res_x_bs_ue, h_bs_ue, l_bs_ue, rb_req)
    P = compute_P(bs_status, res_x_bs_ue, rb_req)
    return B / P


# 计算碳效 CE
def compute_CE(res_x_bs_ue, p_pv, bs_status, h_bs_ue, l_bs_ue, rb_req):
    B = compute_B(res_x_bs_ue, h_bs_ue, l_bs_ue, rb_req)
    E = compute_E(res_x_bs_ue, p_pv, bs_status, rb_req)
    return B / E


def compute_p_available(res_t_bs_bs, res_C, res_D, p_pv):
    p_available = p_pv + const.BETA * np.expand_dims(np.sum(res_t_bs_bs, 0), 0) - np.expand_dims(np.sum(res_t_bs_bs, 1),
                                                                                                 0) - res_C + const.ETA_BATTERY * res_D

    return p_available  # shape=[1,bs_num]
